TARGET 		: Cruehead crackme3
PROTECTION 	: Keyfile

TOOLS USED 	: W32DASM, SoftIce, HexWorkshop

Load up the crackme in W32dasm, it does not seem to be packed :)
Check the importlist for ReadFile. We find it at the beginning of the file :

:00401016 6A00                    push 00000000
:00401018 6880000000              push 00000080
:0040101D 6A03                    push 00000003
:0040101F 6A00                    push 00000000
:00401021 6A03                    push 00000003
:00401023 68000000C0              push C0000000

* Possible StringData Ref from Data Obj ->"CRACKME3.KEY"
                                  |
:00401028 68D7204000              push 004020D7 // The name of our KeyFile

* Reference To: KERNEL32.CreateFileA, Ord:0000h
                                  |
:0040102D E876040000              Call 004014A8
:00401032 83F8FF                  cmp eax, FFFFFFFF
:00401035 750C                    jne 00401043	//Jump if the file is there

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040106D(C), :0040109F(C)
|

* Possible StringData Ref from Data Obj ->"CrackMe v3.0             "
                                  |
:00401037 680E214000              push 0040210E	
:0040103C E8B4020000              call 004012F5
:00401041 EB6B                    jmp 004010AE	// Jump Unregistered

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401035(C)
|
:00401043 A3F5204000              mov dword ptr [004020F5], eax // Save handle
:00401048 B812000000              mov eax, 00000012	    	// Keylength=12h
:0040104D BB08204000              mov ebx, 00402008		// Bufferaddress
:00401052 6A00                    push 00000000
:00401054 68A0214000              push 004021A0			// # of Bytes read
:00401059 50                      push eax			// # of Bytes to read
:0040105A 53                      push ebx			// Buffer	
:0040105B FF35F5204000            push dword ptr [004020F5]	// FileHandle

* Reference To: KERNEL32.ReadFile, Ord:0000h
                                  |
:00401061 E830040000              Call 00401496			     // Call ReadFile
:00401066 833DA021400012          cmp dword ptr [004021A0], 00000012 // Check Keylength with 12
:0040106D 75C8                    jne 00401037			     // Bad-guy jump
:0040106F 6808204000              push 00402008			     // Push buffer
:00401074 E898020000              call 00401311			     // Call 'decodestring' (***)
:00401079 8135F920400078563412    xor dword ptr [004020F9], 12345678 // xor hash
:00401083 83C404                  add esp, 00000004
:00401086 6808204000              push 00402008
:0040108B E8AC020000              call 0040133C			    // EAX points to 4 last bytes of key
:00401090 83C404                  add esp, 00000004
:00401093 3B05F9204000            cmp eax, dword ptr [004020F9]	     // Compare hash with last 4 bytes of key	
:00401099 0F94C0                  sete al
:0040109C 50                      push eax
:0040109D 84C0                    test al, al
:0040109F 7496                    je 00401037			     // Badguy jump
...


(***)

:00401311 33C9                    xor ecx, ecx
:00401313 33C0                    xor eax, eax
:00401315 8B742404                mov esi, dword ptr [esp+04]		//pointer to buffer
:00401319 B341                    mov bl, 41				//Move 'A' to bl

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401333(C)
|
:0040131B 8A06                    mov al, byte ptr [esi]		// Move byte of key to al
:0040131D 32C3                    xor al, bl				// XOR key-byte with bl
:0040131F 8806                    mov byte ptr [esi], al		// Save result in buffer
:00401321 46                      inc esi				// Move pointer 1 byte
:00401322 FEC3                    inc bl				// Move next alfabeth letter in bl
:00401324 0105F9204000            add dword ptr [004020F9], eax		// Add result with hash
:0040132A 3C00                    cmp al, 00				
:0040132C 7407                    je 00401335
:0040132E FEC1                    inc cl				// inc counter
:00401330 80FB4F                  cmp bl, 4F				// End after 14 bytes (bl='O')
:00401333 75E6                    jne 0040131B				

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040132C(C)
|
:00401335 890D49214000            mov dword ptr [00402149], ecx
:0040133B C3                      ret

Well, everything should be clear by now. This crackme is very well, and clean coded!

Summery  :
The crackme looks for CRACKME3.KEY, reads it (401061), and checks if the keylength is 18 bytes.
If it is, it XOR's the first 14 bytes of the key with 'ABCDEFGHIJKLNMO' and adds the results of every XOR in a hash [004020F9]. The key is overwritten with the xored string.
Then the hash is xorred with 12345678, and compared with the last 4 bytes of your key.

Now, make the file 'crackme3.key', and insert an 18 byte key. Let's quickly patch 40109F, and C what happens... A MessageBox saying 'Cracked by <xorred string>'

So, now we know that the xorred string should be our name. Ok, the most easy way top calculate the key out of our name, is letting the program do it for us :)

Enter your name in the KeyFile, and add spaces till you have 14 bytes,and add 4 bytes for hash. Break your program at 401093, and do 'd 402008' in SoftIce. Write down the first 14 bytes, it's the KeyString we need to enter in the KeyFile. Now do 'd 4020F9' to see what the hash should be. Write it down too, these are the final 4 bytes.
Start Hexworkshop, enter the 14 and 4 bytes in the file. Start the program, and we are registered :)

Key in file for Detten : 	05 27 37 30 20 28 67 68 69 6A 6B 6C 6D 6E 	1C 55 34 12
			     		    XORRED NAMESTRING		    	    HASH

Rename crackme3.ke_ to crackme3.key for an example.
 
That's it, check www.biw-reversing.cjb.net for more tutorials.

Greetings,

Detten
Detn@hotmail.com